home *** CD-ROM | disk | FTP | other *** search
- /*********************************************************************
- File : GUSI - Grand Unified Socket Interface
- File : GUSIINETTest - Test unix domain sockets
- Author : Matthias Neeracher <neeri@iis.ethz.ch>
- Started : 02Sep92
- Modified : 08Sep92 MN First attempt
- 08Sep92 MN Factor out common socket routines
- 14Sep92 MN Misinterpreted hostent structure
- 03Mar93 MN Added performance test
- 29Jul93 MN servent tests
- 25Aug93 MN gethostbyaddr()
- Last : 25Aug93
- *********************************************************************/
-
- #define Int4 long
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <netdb.h>
- #include <ctype.h>
- #include <pwd.h>
- #include <varargs.h>
- #include <errno.h>
- #include <arpa/telnet.h>
- #include <netinet/in_systm.h>
- #include <machine/endian.h>
- #include <netinet/ip.h>
- #include <arpa/inet.h>
- #include <string.h>
- //#include <sock_ext.h>
- int s_select(Int4 width, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
- int sscanf(const char *, char *, ...);
-
- #define NROFCHARS 26
- #define DECODE(ch) ((ch) ? (ch) - (isupper(ch) ? 'A' : 'a') + 1 : 0)
- #define CMDCODE(ch1,ch2) (DECODE(ch1)*(NROFCHARS+1)+DECODE(ch2))
- #define NROFCMDS (NROFCHARS+1)*(NROFCHARS+1)
-
- typedef void (*TestCmd)(char ch1, char ch2, const char * restcmd);
-
- typedef struct {
- TestCmd proc;
- const char * syntax;
- const char * help;
- } CmdDef;
-
- CmdDef commands[NROFCMDS];
-
- #define DISPATCH(ch1,ch2) commands[CMDCODE(ch1,ch2)].proc
- #define USAGE(ch1,ch2) commands[CMDCODE(ch1,ch2)].syntax
- #define HELPMSG(ch1,ch2) commands[CMDCODE(ch1,ch2)].help
-
-
- #ifndef MAXHOSTNAMELEN
- #define MAXHOSTNAMELEN 64
- #endif MAXHOSTNAMELEN
-
- int inputline;
-
- #define Boolean unsigned char
-
- /* void COMMAND(
- char ch1, char ch2, Command name
- TestCmd p, Command to be run
- char * s, Arguments to command
- char * h); Explanation for command
-
- Example:
- COMMAND('m', 'd', MkDir, "directory", "Make a new directory");
- */
-
- #define COMMAND(ch1,ch2,p,s,h) \
- DISPATCH(ch1,ch2) = (p), \
- USAGE(ch1,ch2) = (s), \
- HELPMSG(ch1,ch2) = (h)
-
- /* An useful macro for dumping variables.
-
- Example:
- DUMP(statbuf.st_dev,d);
- */
-
- #define DUMP(EXPR, MODE) printf("# %s = %"#MODE"\n", #EXPR, EXPR)
-
- Boolean HellHoundOnMyTrail = 1; /* Gotta keep on moving */
- char infilename[200];
- char * inputfrom;
- int inputline;
- CmdDef commands[NROFCMDS];
-
- void Help(char _1, char _2, const char *_3)
- {
- char ch1,ch2;
-
- printf("Commands are:\n\n");
-
- for (ch1 = 'a'; ch1 <= 'z'; ++ch1)
- for (ch2 = 0; ch2 <= 'z'; ch2 ? ++ch2 : (ch2 = 'a'))
- if (HELPMSG(ch1,ch2))
- printf(
- "\t%c%c %-25s -- %s\n",
- ch1,
- ch2 ? ch2 : ' ',
- USAGE(ch1,ch2),
- HELPMSG(ch1,ch2));
-
- printf("\n");
- }
-
- void Where()
- {
- if (inputfrom)
- printf("File '%s'; Line %d\n", inputfrom, inputline);
- }
-
- void Prompt()
- {
-
- if (!inputfrom)
- printf("[%d] ", inputline );
- }
-
- #define CASE(code) case code: return #code
-
- const char * Explain()
- {
- switch (errno) {
- CASE(EPERM);
- CASE(ENOENT);
- CASE(ESRCH);
- CASE(EINTR);
- CASE(EIO);
- CASE(ENXIO);
- CASE(E2BIG);
- CASE(ENOEXEC);
- CASE(EBADF);
- CASE(ECHILD);
- CASE(EDEADLK);
- CASE(ENOMEM);
- CASE(EACCES);
- CASE(EFAULT);
- CASE(ENOTBLK);
- CASE(EBUSY);
- CASE(EEXIST);
- CASE(EXDEV);
- CASE(ENODEV);
- CASE(ENOTDIR);
- CASE(EISDIR);
- CASE(EINVAL);
- CASE(ENFILE);
- CASE(EMFILE);
- CASE(ENOTTY);
- CASE(ETXTBSY);
- CASE(EFBIG);
- CASE(ENOSPC);
- CASE(ESPIPE);
- CASE(EROFS);
- CASE(EMLINK);
- CASE(EPIPE);
- CASE(EDOM);
- CASE(ERANGE);
- CASE(EWOULDBLOCK);
- CASE(EINPROGRESS);
- CASE(EALREADY);
- CASE(ENOTSOCK);
- CASE(EDESTADDRREQ);
- CASE(EMSGSIZE);
- CASE(EPROTOTYPE);
- CASE(ENOPROTOOPT);
- CASE(EPROTONOSUPPORT);
- CASE(ESOCKTNOSUPPORT);
- CASE(EOPNOTSUPP);
- CASE(EPFNOSUPPORT);
- CASE(EAFNOSUPPORT);
- CASE(EADDRINUSE);
- CASE(EADDRNOTAVAIL);
- CASE(ENETDOWN);
- CASE(ENETUNREACH);
- CASE(ENETRESET);
- CASE(ECONNABORTED);
- CASE(ECONNRESET);
- CASE(ENOBUFS);
- CASE(EISCONN);
- CASE(ENOTCONN);
- CASE(ESHUTDOWN);
- CASE(ETOOMANYREFS);
- CASE(ETIMEDOUT);
- CASE(ECONNREFUSED);
- CASE(ELOOP);
- CASE(ENAMETOOLONG);
- CASE(EHOSTDOWN);
- CASE(EHOSTUNREACH);
- CASE(ENOTEMPTY);
- CASE(EPROCLIM);
- CASE(EUSERS);
- CASE(EDQUOT);
- CASE(ESTALE);
- CASE(EREMOTE);
- CASE(EBADRPC);
- CASE(ERPCMISMATCH);
- CASE(EPROGUNAVAIL);
- CASE(EPROGMISMATCH);
- CASE(EPROCUNAVAIL);
- CASE(ENOLCK);
- CASE(ENOSYS);
- default:
- return "Unknown";
- }
- }
-
- void Usage(char ch1, char ch2)
- {
- printf("# Usage is: %c%c %s\n", ch1, ch2 ? ch2 : ' ', USAGE(ch1,ch2));
- Where();
- }
-
- void Dispatch(const char * command)
- {
- char ch1 = command[0];
- char ch2 = command[1];
- TestCmd exec;
-
- /* We are guaranteed to have at least one valid character */
-
- switch (ch1) {
- case '\n':
- case '#':
- return;
- }
-
- if (!ch2)
- ++command;
- else {
- if (isspace(ch2)) {
- command += 1;
- ch2 = 0;
- } else
- command += 2;
-
- /* Skip rest of first word */
- for (; *command && !isspace(*command); ++command);
-
- /* Skip whitespace */
- while (isspace(*command))
- ++command;
- }
-
- if (isalpha(ch1) && (!ch2 || isalpha(ch2)) && (exec = DISPATCH(ch1,ch2)))
- exec(ch1, ch2, command);
- else {
- if (ch2)
- printf("# Unknown command: '%c%c'\n", ch1, ch2);
- else
- printf("# Unknown command: '%c'\n", ch1);
-
- printf("# Type 'h' for a list of known commands.\n");
-
- Where();
- }
- }
-
- void Quit(char _1, char _2, const char *_3)
- {
- HellHoundOnMyTrail = 0;
- }
-
- void RunTest(int argc, char ** argv)
- {
-
- char cmd[80];
-
- COMMAND('h', 0, Help, "", "Print this list");
- COMMAND('q', 0, Quit, "", "End the sad existence of this program");
-
- if (!--argc)
- Help('h', 0, "");
-
- do {
- inputfrom = 0;
-
- inputline = 1;
-
- while (HellHoundOnMyTrail && (Prompt(), gets(cmd))) {
- Dispatch(cmd);
- ++inputline;
- }
- } while (HellHoundOnMyTrail && --argc > 0);
-
- printf("So long, it's been good to know you.\n");
- }
-
- int sock; /* Socket to read/write to */
- int accsock; /* Socket to accept connections on */
- char addrstr[100];
-
- void Socket(char ch1, char _2, const char *_3)
- {
- sock = socket(AF_INET, (ch1 == 's') ? SOCK_STREAM : SOCK_DGRAM, 0);
-
- if (sock == -1) {
- printf("# socket() returned error %s\n", Explain());
- Where();
- }
- }
-
- void Bind(char ch1, char ch2, const char * cmd)
- {
- int len;
- struct sockaddr_in addr;
-
- if (sock == -1) {
- printf("# socket is not open\n");
- Where();
-
- return;
- }
-
- if (sscanf(cmd, "%s %hd", addrstr, &addr.sin_port) == 2) {
- addr.sin_addr.s_addr = inet_addr(addrstr);
- addr.sin_family = AF_INET;
- len = sizeof(struct sockaddr_in);
- } else {
- Usage(ch1, ch2);
- return;
- }
-
- if (bind(sock, (struct sockaddr *) &addr, len)) {
- printf(
- "bind(%s:%d) returned error %s\n",
- inet_ntoa(addr.sin_addr),
- addr.sin_port,
- Explain());
-
- Where();
- }
- }
-
- void Accept(char _1, char _2, const char *_3)
- {
- int len;
- struct sockaddr_in addr;
-
- if (sock == -1) {
- printf("# socket is not open\n");
- Where();
-
- return;
- }
- if (accsock != -1) {
- printf("# can't accept more than one connection\n");
- Where();
-
- return;
- }
-
- len = sizeof(struct sockaddr_in);
- sock = accept(accsock = sock, (struct sockaddr *) &addr, &len);
-
- if (sock < 0) {
- printf("# accept() returned error %s\n", Explain());
- sock = accsock;
- accsock = -1;
- } else {
- printf(
- "# accepted connection from %s port %d\n",
- inet_ntoa(addr.sin_addr),
- addr.sin_port);
- }
-
- Where();
- }
-
- void Connect(char ch1, char ch2, const char * cmd)
- {
- int len;
- struct sockaddr_in addr;
-
- if (sock == -1) {
- printf("# socket is not open\n");
- Where();
-
- return;
- }
-
- if (sscanf(cmd, "%s %hd", addrstr, &addr.sin_port) == 2) {
- addr.sin_addr.s_addr = inet_addr(addrstr);
- addr.sin_family = AF_INET;
- len = sizeof(struct sockaddr_in);
- } else {
- Usage(ch1, ch2);
- return;
- }
-
- if (connect(sock, (struct sockaddr *) &addr, len)) {
- printf(
- "connect(%s:%d) returned error %s\n",
- inet_ntoa(addr.sin_addr),
- addr.sin_port,
- Explain());
- Where();
- }
- }
-
- #include <sys/time.h>
-
- int ReadWhileUCan()
- {
- int res;
- char * outline;
- fd_set rdfds;
- fd_set exfds;
- struct timeval delay;
- char out[500];
-
- for (;;) {
- FD_ZERO(&rdfds);
- FD_ZERO(&exfds);
-
- FD_SET(sock, &rdfds);
- FD_SET(sock, &exfds);
-
- delay.tv_sec = 1;
- delay.tv_usec = 0;
-
- res = select(sock+1, &rdfds, 0, &exfds, &delay);
-
- if (res < 0) {
- printf("# select() returned error %s\n", Explain());
-
- return -1;
- } else if (!res)
- return 0;
- else if (res && FD_ISSET(sock, &exfds)) {
- printf("# select() returned an exception\n");
-
- return -1;
- } else if (res && FD_ISSET(sock, &rdfds)) {
- res = read(sock, out, 500);
-
- if (res < 0) {
- printf("# read() returned error %s\n", Explain());
-
- return -1;
- }
-
- out[res] = 0;
-
- for (outline = strtok(out, "\n\r"); outline; outline = strtok(NULL, "\n\r"))
- printf("%s\n", outline);
- }
- }
- }
-
- void Telnet(char _1, char _2, const char *_3)
- {
- int len;
- int part;
- int res;
- char * line;
- char * outline;
- fd_set rdfds;
- fd_set wrfds;
- fd_set exfds;
- struct timeval delay;
- char in[100];
- char out[500];
-
- if (sock == -1) {
- printf("# socket is not open\n");
- Where();
-
- return;
- }
-
- printf("# Entering Poor Man's Telnet mode\n");
-
- for (;;) {
- if (ReadWhileUCan())
- break;
-
- Prompt();
-
- if (!gets(in))
- break;
-
- ++inputline;
-
- if (!strcmp(in, ".\n"))
- break;
-
- if (!strcmp(in, "?\n"))
- continue;
-
- len = strlen(in);
- in[len++] = '\r';
- in[len] = 0;
-
- for (line = in; len; len -= part, line += part) {
- part = 0;
-
- FD_ZERO(&rdfds);
- FD_ZERO(&wrfds);
- FD_ZERO(&exfds);
-
- FD_SET(sock, &rdfds);
- FD_SET(sock, &wrfds);
- FD_SET(sock, &exfds);
-
- delay.tv_sec = 10;
- delay.tv_usec = 0;
-
- res = select(sock+1, &rdfds, &wrfds, &exfds, &delay);
-
- if (res < 0) {
- printf("# select() returned error %s\n", Explain());
-
- return;
- } else if (!res) {
- printf("# select() timed out\n");
-
- return;
- } else if (FD_ISSET(sock, &exfds)) {
- printf("# select() returned an exception\n");
-
- return;
- }
-
- if (FD_ISSET(sock, &rdfds)) {
- res = read(sock, out, 500);
-
- if (res < 0) {
- printf("# read() returned error %s\n", Explain());
-
- return;
- }
-
- out[res] = 0;
-
- for (outline = strtok(out, "\n\r"); outline; outline = strtok(0, "\n\r"))
- printf("%s\n", outline);
- } else if (FD_ISSET(sock, &wrfds)) {
- res = write(sock, line, len);
-
- if (res < 0) {
- line[strlen(line) - 2] = 0;
- printf("# write(\"%s\") returned error %s\n", line, Explain());
-
- return;
- }
-
- part = res;
- }
- }
- }
-
- printf("# Leaving Poor Man's Telnet mode\n");
- }
-
- void N2Addr(char ch1, char ch2, const char * cmd)
- {
- struct in_addr addr;
- struct hostent * ent;
-
- if (sscanf(cmd, "%s", addrstr) == 1)
- if (ent = gethostbyname(addrstr)) {
- memcpy(&addr, ent->h_addr, sizeof(struct in_addr));
- printf("# gethostbyname(%s) returned %s\n", addrstr, inet_ntoa(addr));
- } else
- printf("# gethostbyname(%s) failed.\n", addrstr);
- else
- Usage(ch1, ch2);
- }
-
- void A2Name(char ch1, char ch2, const char * cmd)
- {
- struct in_addr addr;
- struct hostent * ent;
-
- if (sscanf(cmd, "%s", addrstr) == 1) {
- addr.s_addr = inet_addr(addrstr);
- if (ent = gethostbyaddr((void *) &addr, 0, 0)) {
- printf("# gethostbyaddr(%s) returned %s\n", addrstr, ent->h_name);
- } else
- printf("# gethostbyaddr(%s) failed.\n", addrstr);
- } else
- Usage(ch1, ch2);
- }
-
- void PerfTest(char ch1, char ch2, const char * cmd)
- {
- }
-
- void ServByName(char ch1, char ch2, const char * cmd)
- {
- struct servent * ent;
- char proto[6];
-
- if (sscanf(cmd, "%s %s", addrstr, proto) == 2)
- if (ent = getservbyname(addrstr, proto))
- printf("# getservbyname(%s %s) returned %d\n", addrstr, proto, ent->s_port);
- else
- printf("# getservbyname(%s %s) failed.\n", addrstr, proto);
- else if (sscanf(cmd, "%s", addrstr) == 1)
- if (ent = getservbyname(addrstr, NULL))
- printf("# getservbyname(%s) returned %d\n", addrstr, ent->s_port);
- else
- printf("# getservbyname(%s) failed.\n", addrstr);
- else
- Usage(ch1, ch2);
- }
-
- void PrintServEnt(struct servent * ent, Boolean full)
- {
- char ** al;
-
- printf("%s", ent->s_name);
-
- if (full)
- printf(" %d/%s", ent->s_port, ent->s_proto);
-
- for (al = ent->s_aliases; *al; ++al)
- printf(" %s", *al);
-
- putchar('\n');
- }
-
- void ServByPort(char ch1, char ch2, const char * cmd)
- {
- }
-
- void ServList(char _1, char _2, const char *_3)
- {
- }
-
- test(void)
- {
- char *argv[] = {"test", 0};
-
- printf("GUSIINETTest MN 25Aug93\n\n");
-
- COMMAND('s', 's', Socket, "", "Create a stream socket");
- COMMAND('d', 's', Socket, "", "Create a datagram socket");
- COMMAND('b', 'd', Bind, "addr port", "Bind to address");
- COMMAND('c', 'o', Connect, "addr port", "Connect to address");
- COMMAND('a', 'c', Accept, "", "Accept a connection");
- COMMAND('t', 'n', Telnet, "", "Play telnet");
- COMMAND('n', 'a', N2Addr, "name", "Convert name to address");
- COMMAND('a', 'n', A2Name, "addr", "Convert address to name");
- COMMAND('p', 't', PerfTest,"count", "Do a performance test");
- COMMAND('s', 'n', ServByName, "name", "Convert service name to port number");
- COMMAND('s', 'p', ServByPort, "port", "Convert port number to service name");
- COMMAND('s', 'l', ServList, "", "List services");
-
- RunTest(1, argv);
- }
-